/////////////////////////////////////////
// 操作websocket
/////////////////////////////////////////

//创建 websocket实例
let websocket = new WebSocket("ws://113.44.83.92:1209/WebSocketMessage");

websocket.onopen = function () {
  console.log("wesocket 连接成功！");
};
websocket.onmessage = function (e) {
  console.log("wesocket 收到消息！" + e.data);
  let resp = JSON.parse(e.data);
  if (resp.type == "message") {
    //处理消息响应
    handleMessage(resp);
  } else {
    console.log("resp.type不符合要求！");
  }
};
websocket.onclose = function () {
  console.log("wesocket 连接关闭！");
};
websocket.onerror = function () {
  console.log("wesocket 连接异常！");
};

function handleMessage(resp) {
  //把客户端收到的消息，展示到
  //右侧的主消息区。（这里有个前提，是会话处理被选中区域）
  //在会话预览区域也需要显示。就需要获取到这个消息属于哪个会话

  //1.根据响应中的SessionId获取到当前会话对应的里、标签
  //如果li标签不存在，就要创建一个新的
  // 其他操作, 还可以在会话窗口上给个提示 (红色的数字, 有几条消息未读), 还可以播放个提示音.
  // 这些操作都是纯前端的. 实现也不难, 不是咱们的重点工作. 暂时不做了.
  //2.把新的消息，显示到绘画的预览区域（li标签的p标签中）如果消息太长要截断
  //3.把收到的消息的会话，放到会话列表最上面
  //4.如果收到消息会话处于被选中状态，则把当前消息给放到右边列表中
  //新增消息的同时，要调整滚动条的位置，保证新消息虽然在底部，但能被用户看到
  //其他操作，还可以在会话窗口上给个提示，红色数字有几条未读，还可以放个提示音
  //这些操作都是纯前端操作，实现也不难，不是我们重点工作，暂时不做

  //1.根据响应中的SessionId获取到当前会话对应的里、标签
  let curSessionLi = findSessionLi(resp.sessionId);
  if (curSessionLi == null) {
    // 就需要创建出一个新的 li 标签, 表示新会话.
    curSessionLi = document.createElement("li");
    curSessionLi.setAttribute("message-session-id", resp.sessionId);
    // 此处 p 标签内部应该放消息的预览内容. 一会后面统一完成, 这里先置空
    curSessionLi.innerHTML = "<h3>" + resp.fromName + "</h3>" + "<p></p>";
    // 给这个 li 标签也加上点击事件的处理
    curSessionLi.onclick = function () {
      clickSession(curSessionLi);
    };
  }
  // 2. 把新的消息, 显示到会话的预览区域 (li 标签里的 p 标签中)
  //    如果消息太长, 就需要进行截断.
  let p = curSessionLi.querySelector("p");
  p.innerHTML = resp.content;
  if (p.innerHTML.length > 10) {
    p.innerHTML = p.innerHTML.substring(0, 10) + "...";
  }
  // 3. 把收到消息的会话, 给放到会话列表最上面.
  let sessionListUL = document.querySelector("#session-list");
  sessionListUL.insertBefore(curSessionLi, sessionListUL.children[0]);
  // 4. 如果当前收到消息的会话处于被选中状态, 则把当前的消息给放到右侧消息列表中.
  //    新增消息的同时, 注意调整滚动条的位置, 保证新消息虽然在底部, 但是能够被用户直接看到.
  if (curSessionLi.className == "selected") {
    // 把消息列表添加一个新消息.
    let messageShowDiv = document.querySelector(".right .message-show");
    addMessage(messageShowDiv, resp);
    scrollBottom(messageShowDiv);
  }
}


function findSessionLi(targetSessionId) {
  // 获取到所有的会话列表中的 li 标签
  let sessionLis = document.querySelectorAll("#session-list li");
  for (let li of sessionLis) {
    let sessionId = li.getAttribute("message-session-id");
    if (sessionId == targetSessionId) {
      return li;
    }
  }
  // 啥时候会触发这个操作, 就比如如果当前新的用户直接给当前用户发送消息, 此时没存在现成的 li 标签
  return null;
}

/////////////////////////////////////////
//实现发送按钮，并输出消息
/////////////////////////////////////////
initSendButton();
function initSendButton() {
  //1.获取发送按钮 和 消息输入框
  let sendButton = document.querySelector(".right .ctrl");
  let messageInput = document.querySelector(".right .message-input");

  //2.给发送按钮一个点击事件
  sendButton.onclick = function () {
    if (!messageInput.value) {
      //value的值是null或者''都会触发这个条件
      return;
    }
    //获取当前选中的 li 标签的 sessionId
    let selectedLi = document.querySelector("#session-list .selected");
    if (selectedLi == null) {
      //当前标签未被选择
      return;
    }
    let sessionId = selectedLi.getAttribute("message-session-id");

    //构造json数据
    let req = {
      type: "message",
      sessionId: sessionId,
      content: messageInput.value,
    };
    req = JSON.stringify(req);
    console.log("[websocket] send:" + req);
    //通过websocket发送消息
    websocket.send(req);
    //发送完清空输入框
    messageInput.value = "";
  };
}

/////////////////////////////////////////
//这里实现 消息 和 好友 标签页的切换
/////////////////////////////////////////
initSwitchTab();
function initSwitchTab() {
  //1.先获取到相关元素（标签页的按钮，会话列表，好友列表）
  let tabSession = document.querySelector(".tab .tab-session");
  let tabFriend = document.querySelector(".tab .tab-friend");
  //同时选中多个元素，得到的是个数组
  //[0] 就是会话列表
  //[1] 就是好友列表
  let lists = document.querySelectorAll(".list");

  //2.针对标签页按钮，注册点击事件
  //如果点击的会话标签按钮，显示会话，隐藏好友
  //如果是好友，则显示好友，隐藏会话
  tabSession.onclick = function () {
    //设置图标
    tabSession.style.backgroundImage = "url(pic/对话.png)";
    tabFriend.style.backgroundImage = "url(pic/好友2.png)";
    //考虑好代码真正执行是在哪个文件里面.真正执行代码位置在client.html
    //
    lists[0].style.display = "block"; // 显示会话列表
    lists[1].style.display = "none"; // 隐藏好友列表
  };
  tabFriend.onclick = function () {
    //设置图标
    tabSession.style.backgroundImage = "url(pic/对话2.png)";
    tabFriend.style.backgroundImage = "url(pic/好友.png)";
    lists[0].style.display = "none"; // 隐藏会话列表
    lists[1].style.display = "block"; // 显示好友列表
  };
}

//获取用户信息
getUserInfo();
function getUserInfo() {
  $.ajax({
    type: "get",
    url: "/user/userInfo",
    success: function (result) {
      console.log(result);

      //从服务器获取数据。校验结果是否有效，无效则跳转到登录页面
      //有效则把用户名显示到界面上
      //同时也可以记录userId到html标签的属性中，后面可能用
      if (result.userId && result.userId > 0) {
        //如果用户存在。且有效
        $(".main .left .user").text(result.username);
        $(".main .left .user").attr("user-id", result.userId);
      } else {
        alert("当前用户未登录！");
        location.assign("login.html");
      }
    },
  });
}

//获取好友列表
getFriendList();
function getFriendList() {
  $.ajax({
    type: "get",
    url: "/friend/friendList",
    success: function (result) {
      //1.先把之前的好友列表清空
      let friendListUL = document.querySelector("#friend-list");
      friendListUL.innerHTML = "";
      //2.遍历result，把服务器响应的结果追加到当前的friend-list中
      for (let friend of result) {
        let li = document.createElement("li");
        li.innerHTML = "<h4>" + friend.friendName + "</h4>";

        li.setAttribute("friend-id", friend.friendId);
        friendListUL.appendChild(li);

        //每个li标签，对应界面上的一个好友选项，给这个li加上点击事件的处理。
        li.onclick = function () {
          clickFriend(friend);
        };
      }
    },
    error: function () {
      console.log("获取好友列表失败！");
    },
  });
}
//获取会话列表
getSessionList();
function getSessionList() {
  $.ajax({
    type: "get",
    url: "/session/sessionList",
    success: function (result) {
      //1.清空之前的会话列表
      let sessionListUL = document.querySelector("#session-list");
      sessionListUL.innerHTML = "";
      //2.遍历响应数据，针对结果来构造页面
      for (let session of result) {
        //追对针对lastMessage的长度进行截断处理
        if (session.lastMessage.length > 10) {
          session.lastMessage = session.lastMessage.substring(0, 10) + "...";
        }

        let li = document.createElement("li");
        li.setAttribute("message-session-id", session.sessionId);
        console.log(session.sessionId);
        console.log(session.friends);
        console.log(session.friends.friendId);
        console.log(session.friends.friendName);
        /* 由于friend是一个数组。而不是对象。因此不能.friendId和.friendName */
        li.innerHTML =
          "<h3>" +
          session.friends[0].friendName +
          "</h3>" +
          "<p>" +
          session.lastMessage +
          "</p>";
        sessionListUL.appendChild(li);

        //给li标签加上点击事件
        li.onclick = function () {
          clickSession(li);
        };
      }
    },
  });
}

function clickSession(currentLi) {
  //用于移除在未选中好友状态下的聊天框的背景图片
  let messageShow = document.querySelector(".message-show");
  if (messageShow) {
    messageShow.classList.remove("empty");
  } else {
    console.log("#message-show 元素未找到");
  }

  //1.设置active
  let allLis = document.querySelectorAll("#session-list>li");
  activeSession(allLis, currentLi);
  //2.获取指定会话的历史消息
  let sessionId = currentLi.getAttribute("message-session-id");
  console.log(sessionId);
  getHistoryMessage(sessionId);
}

function activeSession(allLis, currentLi) {
  //主要为了取消未被选中状态的li标签的className
  for (let li of allLis) {
    if (li == currentLi) {
      li.className = "selected";
    } else {
      li.className = "";
    }
  }
}

//获得历史消息
function getHistoryMessage(sessionId) {
  console.log("获取历史消息 sessionId=" + sessionId);
  //1.先清空右侧列表中已有的内容
  let titleDiv = document.querySelector(".right .title");
  titleDiv.innerHTML = "";
  let messageShowDiv = document.querySelector(".right .message-show");
  messageShowDiv.innerHTML = "";

  //2.重新设置会话标题，先找到选中的会话是哪个。被选中的会话带有selected类的
  let selectedH3 = document.querySelector("#session-list .selected>h3");
  if (selectedH3) {
    //如果找到了设置，没找到就不管了
    titleDiv.innerHTML = selectedH3.innerHTML;
  }

  //3.获取历史消息
  $.ajax({
    type: "get",
    url: "message?sessionId=" + sessionId,
    success: function (result) {
      //此处result是一个js对象数组，因此直接遍历就可以
      for (let message of result) {
        addMessage(messageShowDiv, message);
      }

      //控制滚动条，自动滚动到最下
      scrollBottom(messageShowDiv);
    },
  });
}

//把messageShow里的内容滚动到底部
function scrollBottom(elem) {
  //获取可视区域高低
  let clientHeight = elem.offsetHeight;
  //获取内容高度
  let scrollHeight = elem.scrollHeight;
  //3.进行滚动操作
  elem.scrollTo(0, scrollHeight - clientHeight);
}

function addMessage(messageShowDiv, message) {
  let messageDiv = document.createElement("div");
  //此处需要针对当前消息是不是用户自己发的，决定是靠左还是靠右
  let selfUsername = document.querySelector(".left .user").innerHTML;
  if (selfUsername == message.fromName) {
    //消息是自己发的，靠右
    messageDiv.className = "message message-right";
  } else {
    messageDiv.className = "message message-left";
    //消息是别人发的，靠左
  }
  messageDiv.innerHTML =
    '<div class="box">' +
    "<h4>" +
    message.fromName +
    "</h4>" +
    "<p>" +
    message.content +
    "</p>" +
    "</div>";
  messageShowDiv.appendChild(messageDiv);
}

//点击好友列表项触发的函数
function clickFriend(friend) {
  //1.先判断当前好友是否有对应的会话。
  //使用一个单独的函数来实现，这个函数是用户的名字。
  //返回的是一个li标签。找到了就返回对应会话列表；里的li。如果没找到，返回null
  let sessionLi = findSessionByName(friend.friendName);
  let sessionListUL = document.querySelector("#session-list");
  if (sessionLi) {
    //2.如果存在匹配的结果，就把这个会话设置成选中状态，并且置顶。
    sessionListUL.insertBefore(sessionLi, sessionListUL.children[0]);
    //获取历史消息，可以直接调用clickSession。也可以模拟点击操作
    sessionLi.click();
  } else {
    //3.如果不存在，就新建一个会话，创建里、标签+通知服务器。
    sessionLi = document.createElement("li");
    sessionLi.innerHTML = "<h3>" + friend.friendName + "</h3>" + "<p></p>";
    sessionListUL.insertBefore(sessionLi, sessionListUL.children[0]);
    sessionLi.onclick = function () {
      clickSession(sessionLi);
    };
    sessionLi.click();
    //发送消息给服务器。告诉服务器当前会话是啥样的
    createSession(friend.friendId, sessionLi);
  }
  //4.还要把标签页切换到会话列表
  //实现方式很容易，因为只要找到会话列表标签页的按钮，模拟一下点击操作就可以了
  let tableSession = document.querySelector(".tab .tab-session");
  tableSession.click();
}
function findSessionByName(username) {
  //1.先获取到会话列表中所有的li 标签
  //2.然后依次遍历，看看这些li标签谁的名字和查找的名字一致。
  let sessionLis = document.querySelectorAll("#session-list>li");

  for (let sessionLi of sessionLis) {
    //获取li标签里的h3标签，进一步得到名字
    let h3 = sessionLi.querySelector("h3");
    if (h3.innerHTML == username) {
      return sessionLi;
    }
  }
  return null;
}

//friendId 是构造HTTP请求时必备的信息
function createSession(friendId, sessionLi) {
  $.ajax({
    type: "post",
    url: "/session/session?toUserId=" + friendId,
    success: function (result) {
      console.log("创建会话成功!SessionID = " + result.sessionId);
      sessionLi.setAttribute("message-session-id", result.sessionId);
    },
    error: function () {
      console.log("创建会话失败！");
    },
  });
}
